import urllib

__list = {}

class Error(Exception): pass

class Abstract(object):

  def __init__(self, handler, type):
    self.handler = handler
    self.type = type

  def id(self):
    raise Error('user not setup')

  def email(self):
    raise Error('user not setup')

  def name(self):
    raise Error('user not setup')

  def is_authenticated(self):
    raise Error('user not setup')

  def login_url(self, url='/'):
    raise Error('user not setup')

  def logout_url(self, url='/'):
    raise Error('user not setup')

class SessionAbstract(Abstract):

  def __init__(self, handler, type, login_url, logout_url, session_key='user'):
    super(SessionAbstract, self).__init__(handler, type)
    self.__is_setup = False
    self.__login_url = login_url
    self.__logout_url = logout_url
    self.__session_key = session_key
    self.__is_authenticated = False

  def __setup(self):
    if not self.__is_setup:
      self.__is_setup = True
      self.__id = self.handler.session.get('%s_id' % self.__session_key)
      self.__email = self.handler.session.get('%s_email' % self.__session_key)
      self.__name = self.handler.session.get('%s_name' % self.__session_key)
      if self.__id and self.__email:
        self.__is_authenticated = True

  def id(self):
    self.__setup()
    return self.__id

  def email(self):
    self.__setup()
    return self.__email

  def name(self):
    self.__setup()
    return self.__name

  def is_authenticated(self):
    self.__setup()
    return self.__is_authenticated

  def login_url(self, url='/'):
    return self.__login_url.replace('$url', urllib.quote(url, safe=''))

  def logout_url(self, url='/'):
    return self.__logout_url.replace('$url', urllib.quote(url, safe=''))

def get(handler, type='default'):
  global __list
  if type in __list:
    (module, args, kwargs) = __list[type]
    return module(handler, type, *args, **kwargs)
  else:
    return Abstract(handler, type)

def set(module, type, *args, **kwargs):
  global __list
  __list[type] = (module, args, kwargs)
